#include "sys.h"
#include "log.h"
#include "net.h"
#include "cJSON.h"
#include "us_ctl.h"
enum {
    UCTL_CONF_TYPE_INT = 0,
    UCTL_CONF_TYPE_USHORT,
    UCTL_CONF_TYPE_LLONG,
    UCTL_CONF_TYPE_STRING,
};
struct uctl_conf_map {
    char* name;
    long int offset;
    int type;
};
static struct uctl_conf_map conf_map[] = {
    { "cmd", _offset(uctl_conf_t, cmd[0]), UCTL_CONF_TYPE_STRING },
    { "rate", _offset(uctl_conf_t, rate), UCTL_CONF_TYPE_LLONG },
    { "bytes", _offset(uctl_conf_t, bytes), UCTL_CONF_TYPE_LLONG },
    { "packets", _offset(uctl_conf_t, packets), UCTL_CONF_TYPE_LLONG },
    { "blksize", _offset(uctl_conf_t, blksize), UCTL_CONF_TYPE_INT },
    { "duration", _offset(uctl_conf_t, duration), UCTL_CONF_TYPE_INT },
    { "port", _offset(uctl_conf_t, port), UCTL_CONF_TYPE_USHORT },
};


int uctl_conf_struct2str(uctl_conf_t* conf, char* buf, int len)
{
    int i = 0, valueint = 0;
    char llong_str[16] = { 0 };
    char* ptr = (char*)conf;
    cJSON* root = cJSON_CreateObject();

    for (i = 0; i < Array_Size(conf_map); i++) {
        switch (conf_map[i].type) {
        case UCTL_CONF_TYPE_INT:
            valueint = *((int*)(ptr + conf_map[i].offset));
            cJSON_AddNumberToObject(root, conf_map[i].name, valueint);
            break;
        case UCTL_CONF_TYPE_USHORT:
            valueint = *((uint16_t*)(ptr + conf_map[i].offset));
            cJSON_AddNumberToObject(root, conf_map[i].name, valueint);
            break;
        case UCTL_CONF_TYPE_LLONG:
            sprintf(llong_str, "%lld", *((long long*)(ptr + conf_map[i].offset)));
            cJSON_AddStringToObject(root, conf_map[i].name, llong_str);
            break;
        case UCTL_CONF_TYPE_STRING:
            cJSON_AddStringToObject(root, conf_map[i].name, (ptr + conf_map[i].offset));
            break;
            
        }
    }
    ptr = cJSON_Print(root);
    strncpy(buf, ptr, len);
    free(ptr);
    cJSON_Delete(root);
    return 1;
}
int uctl_conf_str2struct(uctl_conf_t* conf, char* buf, int len)
{
    int i = 0;
    char* ptr = (char*)conf;

    cJSON* root = cJSON_Parse(buf);
    if (cJSON_IsNull(root)) {
        log_error("uctl parse json error.");
        return 0;
    }

    for (i = 0; i < Array_Size(conf_map); i++) {
        if (!cJSON_HasObjectItem(root, conf_map[i].name))
            continue;
        cJSON* obj = cJSON_GetObjectItem(root, conf_map[i].name);
        switch (conf_map[i].type) {
        case UCTL_CONF_TYPE_INT:
            *((int*)(ptr + conf_map[i].offset)) = obj->valueint;
            break;
        case UCTL_CONF_TYPE_USHORT:
            *((uint16_t*)(ptr + conf_map[i].offset)) = obj->valueint;
            break;
        case UCTL_CONF_TYPE_LLONG:
            *((long long*)(ptr + conf_map[i].offset)) = atoll(obj->valuestring);
            break;
        case UCTL_CONF_TYPE_STRING:
            strcpy((ptr + conf_map[i].offset), obj->valuestring);
            break;
        }
    }
    cJSON_Delete(root);
    return 1;
}